<?php
/**
 * Short desc
 * 
 * Created by JetBrains PhpStorm.
 * @author zadoev@gmail.com
 * @version 29.03.11 14:19
 * @package ${END}
 */

class RDbBase
{
	protected $_model;
	protected $_field;

	public function __construct( $model, $field )
	{
		$this->_model = $model;
		$this->_field = $field;
	}
	public function __toString()
	{
		return $this->_model->{$this->_field};
	}

	public function getFieldFilter()
	{
		return null;
	}

	public function asGridColumn()
	{
		return $this->_field;
	}

	public function asViewAttribute()
	{
		return $this->_field;
	}

	public function asActiveForm($activeForm, $options = array('template' => '{label} {input} {error}','htmlOptions' => array()) )
	{

		$template = array_key_exists('template', $options) ? $options['template'] :'{label} {input} {error}' ;
		$htmlOptions = array_key_exists('htmlOptions',$options) ? $options['htmlOptions'] : array();
		$template = str_replace('{label}', $activeForm->labelEx($this->_model, $this->_field), $template);
		$template = str_replace('{input}', $this->renderInput($activeForm, $htmlOptions), $template);
		$template = str_replace('{error}', $activeForm->error($this->_model, $this->_field), $template);
		return $template;
	}

	protected function renderInput($activeForm,$htmlOptions)
	{
		return $activeForm->textField($this->_model, $this->_field, $htmlOptions);
	}

    public function asSearchForm($activeForm, $options)
    {
        $template = isset($options['template']) ? $options['template'] :'{label} {input}' ;
        $htmlOptions = isset($options['htmlOptions']) ? $options['htmlOptions'] : array();

        $template = str_replace('{label}', $activeForm->label($this->_model, $this->_field), $template);
        $template = str_replace('{input}', $this->renderInput($activeForm,$htmlOptions), $template);
        return $template;
    }
}

class RDbText extends RDbBase
{
	protected function renderInput($activeForm,$htmlOptions)
	{
        if ( $htmlOptions=== null )
            $htmlOptions = array('rows'=>6, 'cols'=>50);
		return $activeForm->textArea($this->_model, $this->_field, $htmlOptions);
	}

	public function __toString()
	{
		$str = ''.parent::__toString();
		$words = preg_split("/\s+/s", $str);
		if ( count($words) < 2 )
		{
            if ( strlen($str) > 50 )
			    $out =  substr($str, 0, 50).' ...';
            else
                $out = $str;
		}
		else
		{
			$out = '';
			foreach ( $words as $word )
			{
				$out .= $word. ' ';
				if ( strlen( $out ) > 50 )
                {
                    $out .= ' ... ';
					break;
                }
			}
		}
		return $out;

	}

	public function asGridColumn()
	{
		return array(
			'name' => $this->_field,
			'value' => '(string)$data->getField("'.$this->_field.'")',
		);

	}

	public function asViewAttribute()
	{
		return array(
			'name' => $this->_field,
			'value' => (string)$this,
		);
	}

}


class RDbBoolean extends RDbBase
{

	public function __toString()
	{
		return $this->_model->{$this->_field} ? 'true' : 'false';
	}

	public function getFieldFilter()
	{
		return array('0' => 'false', '1' => 'true');
	}

	public function asGridColumn()
	{
		return array(
			'filter' => $this->getFieldFilter(),
			'name' => $this->_field,
			'value' => '(string)$data->getField("'.$this->_field.'")',
		);

	}

	public function asViewAttribute()
	{
		return array(
			'name' => $this->_field,
			'value' => (string)$this,
		);
	}

	protected function renderInput($activeForm,$htmlOptions)
	{
		return $activeForm->checkBox($this->_model, $this->_field,$htmlOptions);
	}

}


class RFieldsManager
{
	public function __construct( $model )
	{
		$fields = $model->getFieldsDescription();
		foreach ( array_diff( array_keys($model->getAttributes()) , array_keys($fields)  ) as $field)
			$this->_fields[$field] = new RDbBase( $model, $field);

		foreach ( $fields as $field => $class )
			$this->_fields[$field ] = new $class( $model, $field);
	}

	public function getField($fieldName)
	{
		return $this->_fields[$fieldName];
	}
}


abstract class RActiveRecord extends CActiveRecord
{
	protected $_fieldsManager = null;


	public function getAdmin()
	{
		$adminClassName = get_class($this).'Admin';

		if ( ! class_exists( $adminClassName,false ) )
			return new RModelAdmin($this);
		return new $adminClassName($this);
	}

	public function getField( $fieldName )
	{
		return $this->getFieldsManager()->getField($fieldName);
	}

	public function getFieldsManager()
	{
		if ( $this->_fieldsManager == null )
			$this->_fieldsManager = new RFieldsManager($this);
		return $this->_fieldsManager;
	}

	/**
	 *
	 * example of return:
	 * <code>
	 * array(
	 *  'fieldName1' => 'FieldType',
	 *  'is_admin' => 'RDbBoolean',
	 *  'description' => 'RDbText',
	 * );
	 * </code>
	 *
	 * @abstract
	 * @return array
	 */
	abstract function getFieldsDescription();
}